package diona.model.pages

import net.liftweb.squerylrecord.KeyedRecord
import net.liftweb.record.{MetaRecord, Record}
import net.liftweb.record.field._
import net.liftweb.squerylrecord.RecordTypeMode._
import java.util.Calendar
import diona.model.PublisherSchema
import diona.search.PostInfo
import org.joda.time.DateTime

/**
 * User: anton
 * Date: 30.07.11 15:23
 */
class PageInfo extends Record[PageInfo] with KeyedRecord[Long]
{
  override def meta = PageInfo

  override val idField = new LongField(this)

  val url = new StringField(this, 1024)
  val date = new DateTimeField(this)
  val isComment = new BooleanField(this)
  val snippet = new OptionalStringField(this, 20000)
  val author = new OptionalStringField(this, 1024)
  val title = new OptionalStringField(this, 1024)
  val site = new StringField(this, 1024)
}

object PageInfo extends PageInfo with MetaRecord[PageInfo]
{
  def table = PublisherSchema.pageInfos

  @volatile var savePosts: Seq[PostInfo] => List[Long] = (posts) => {
    inTransaction {
      val pages = posts
        .map(p => {
        val date = Calendar.getInstance
        date.setTime(p.tstamp.toDate)
        val page: PageInfo = PageInfo.createRecord
          .url(p.url)
          .date(date)
          .isComment(p.isComment)
          .snippet(p.snippet)
          .author(p.author)
          .title(p.title)
          .site(p.site)
        page
      }).toList
      saveOrSelect(pages, List())
    }
  }

  @volatile var byRequestId: Long => List[PageInfo] = requestId => {
    inTransaction {
      join(table, PublisherSchema.searchItems)((p, i) =>
        where(i.requestId === requestId)
        select(p)
        orderBy(p.date desc)
        on(p.id === i.pageId)
      ).distinct.toList
    }
  }

  @volatile var getMinPageDateForTask: Long => Option[DateTime] = taskId => {
    inTransaction {
      join(table, PublisherSchema.searchItems)((p, i) =>
        where(i.taskId === taskId)
        compute(min(p.date))
        on(p.id === i.pageId)
      ).single.measures.map(new DateTime(_))
    }
  }

  def toPostInfo(page: PageInfo): PostInfo =
  {
    new PostInfo(
      url = page.url.is,
      tstamp = new DateTime(page.date.is),
      isComment = page.isComment.is,
      snippet = page.snippet.valueBox,
      author = page.author.valueBox,
      title = page.title.valueBox,
      knownSite = Option(page.site.is)
    )
  }

  private def saveOrSelect(pages: List[PageInfo], ids: List[Long]): List[Long] =
  {
    pages match {
      case p :: tail => saveOrSelect(tail, insertOrSelect(p).id :: ids)
      case Nil => ids
    }
  }

  private def insertOrSelect(page: PageInfo): PageInfo =
  {
    table.where(_.url === page.url).headOption match {
      case Some(p) => p
      case None => table.insert(page)
    }
  }
}